#ifndef __CATALOGO_H__
#define __CATALOGO_H__

#ifndef NULL
#define NULL 0
#endif

#include <iostream>
#include "defines.h"
#include "conjunto.h"
#include "multiconj_materiales.h"
#include "arreglo_redimensionable.h"

using namespace std;

class Catalogo{
	public:
		Catalogo();
		~Catalogo();
		const Conjunto<vivienda> viviendas() const;
		const Multiconj_materiales& materiales(vivienda v) const;
		void agregarVivienda(const Multiconj_materiales& mm);
		nat cantidadViviendas() const;
		nat cantMateriales() const;//devuelve el material mas grande que usa alguna vivienda
		Multiconj_materiales::IterMateriales crearIterMateriales(vivienda v) const;

		//esto es solo para testing! no se deben usar..
		void mostrarCatalogo(ostream&) const;
	private:
		Arreglo_redimensionable<Multiconj_materiales> viviendasMateriales;
		
		Catalogo(const Catalogo&); //constructor por copia                | esto esta en private para que de error
		Catalogo& operator=(const Catalogo&); // operador de asignacion   | cuando se las intente usar
};

Catalogo::Catalogo(){}

Catalogo::~Catalogo(){}

const Conjunto<vivienda> Catalogo::viviendas() const{
	Conjunto<vivienda> conj;
	vivienda v = 0;
	while(v < viviendasMateriales.tam()){
		conj.agregar(v);
		v++;
	}
	return conj;
}

const Multiconj_materiales& Catalogo::materiales(vivienda v) const{
	assert(v<viviendasMateriales.tam());
	return viviendasMateriales.iesimo(v);
}

void Catalogo::agregarVivienda(const Multiconj_materiales& mm){
	viviendasMateriales.extender();
	viviendasMateriales.agregar(mm, viviendasMateriales.tam()-1);
}

nat Catalogo::cantidadViviendas() const{
	return viviendasMateriales.tam();
}

nat Catalogo::cantMateriales() const{
nat m=0;
nat i=0;
nat n=cantidadViviendas();
	while(i<n){
		Multiconj_materiales::IterMateriales it_m = crearIterMateriales(i);
		while(it_m.tieneProximo()){
			nat actual = it_m.avanzar();
			if(actual>m){
				m = actual;
			}
		}
		i++;
	}
	return m;
}

Multiconj_materiales::IterMateriales Catalogo::crearIterMateriales(vivienda v) const{
	return viviendasMateriales.iesimo(v).crearIterMateriales();
}

void Catalogo::mostrarCatalogo(ostream& out) const{
	out << "[";
	int i = 0;
	int j = viviendasMateriales.tam();
	while(i < j){
		out << "<";
		out << i;
		out << ",";
		out << viviendasMateriales.iesimo(i);
		out << ">";
		if(i!=j-1){
		out << ",";
		}
		i++;
	}
	out << "]" << endl;
}


ostream& operator<<(ostream& out, const Catalogo& c) {
	c.mostrarCatalogo(out);
	return out;
}

#endif
